<?php

namespace app\model;

use Laf\Log;
use mon\orm\Model;
use mon\util\Instance;
use mon\util\Container;
use mon\orm\exception\DbException;

/**
 * 权限规则模型
 *
 * Class AuthRule
 * @copyright 2021-03-24 mon-console
 * @version 1.0.0
 */
class AuthRuleModel extends Model
{
    use Instance;

    /**
     * 操作表
     *
     * @var string
     */
    protected $table = 'auth_rule';

    /**
     * 新增自动写入字段
     *
     * @var array
     */
    protected $insert = ['create_time', 'update_time'];

    /**
     * 更新自动写入字段
     *
     * @var array
     */
    protected $update = ['update_time'];

    /**
     * 验证器
     *
     * @var string
     */
    protected $validate = \app\validate\Auth::class;

    /**
     * 权限控制类库模型
     *
     * @var \mon\auth\rbac\model\Rule
     */
    protected $authRuleModel;

    /**
     * 构造方法
     */
    public function __construct()
    {
        $this->authRuleModel = Container::instance()->auth->model('rule');
    }

    /**
     * 查询信息
     *
     * @param array $where where条件
     * @param mixed $field 查询字段
     * @return mixed
     */
    public function getInfo(array $where, $field = '*')
    {
        $info = $this->where($where)->field($field)->find();
        if (!$info) {
            $this->error = '权限规则不存在';
            return false;
        }

        return $info;
    }

    /**
     * 获取树状权限列表
     * 
     * @return array
     */
    public function getTreeList($field = 'id, pid, title', $title = 'title', $where = ['status' => 1])
    {
        $data = $this->where($where)->field($field)->select();
        $tree = Container::instance()->tree;
        $dataArr = $tree->data($data)->getTreeArray(0);
        return $tree->getTreeList($dataArr, $title);
    }

    /**
     * 获取所有有效的路由
     *
     * @return array
     */
    public function getRoute()
    {
        return $this->where('status', 1)->where('methods', '<>', '')->where('callback', '<>', '')->field('name, methods, callback, befor, after')->select();
    }

    /**
     * 新增路由规则
     *
     * @param array $option 请求参数
     * @return boolean
     */
    public function add(array $option)
    {
        $check = $this->validate()->data($option)->scope('add_rule')->check();
        if ($check !== true) {
            $this->error = $this->validate()->getError();
            return false;
        }
        // 判断neme值是否已存在
        $exists = $this->where('name', $option['name'])->find();
        if ($exists) {
            $this->error = '权限规则已存在';
            return false;
        }

        $info = [
            'pid'       => $option['pid'],
            'title'     => $option['title'],
            'name'      => $option['name'],
            'remark'    => isset($option['remark']) ? $option['remark'] : '',
        ];

        $this->startTrans();
        try {
            Log::instance()->oss(__FILE__, __LINE__, 'add rule info', 'sql');
            $save = $this->authRuleModel->add($info, ['status' => $option['status']]);
            if (!$save) {
                $this->rollback();
                $this->error = $this->authRuleModel->getError();
                return false;
            }

            // 记录操作日志
            $record = AdminLogModel::instance()->record(['action' => '新增权限规则', 'content' => json_encode($info, JSON_UNESCAPED_UNICODE)]);
            if (!$record) {
                $this->rollback();
                $this->error = '记录操作日志失败';
                return false;
            }

            $this->commit();
            return true;
        } catch (DbException $e) {
            $this->rollback();
            $this->error = '新增权限规则异常';
            Log::instance()->oss(__FILE__, __LINE__, 'add auth rule exception, msg => ' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 编辑
     *
     * @param array $option 请求参数
     * @return boolean
     */
    public function edit(array $option)
    {
        $check = $this->validate()->data($option)->scope('save_rule')->check();
        if ($check !== true) {
            $this->error = $this->validate()->getError();
            return false;
        }

        $baseInfo = $this->authRuleModel->getInfo(['id' => $option['idx']]);
        if (!$baseInfo) {
            $this->error = $this->authRuleModel->getError();
            return false;
        }
        // 判断neme值是否已存在
        $exists = $this->where('name', $option['name'])->where('id', '<>', $option['idx'])->find();
        if ($exists) {
            $this->error = '路由规则已存在';
            return false;
        }

        $info = [
            'idx'       => $option['idx'],
            'pid'       => $option['pid'],
            'title'     => $option['title'],
            'name'      => $option['name'],
            'remark'    => isset($option['remark']) ? $option['remark'] : '',
            'status'    => $option['status']
        ];

        $this->startTrans();
        try {
            Log::instance()->oss(__FILE__, __LINE__, 'edit rule info', 'sql');
            $save = $this->authRuleModel->modify($info);
            if (!$save) {
                $this->rollback();
                $this->error = $this->authRuleModel->getError();
                return false;
            }

            // 记录操作日志
            $record = AdminLogModel::instance()->record(['action' => '编辑权限规则', 'content' => json_encode($info, JSON_UNESCAPED_UNICODE)]);
            if (!$record) {
                $this->rollback();
                $this->error = '记录操作日志失败';
                return false;
            }

            $this->commit();
            return true;
        } catch (DbException $e) {
            $this->rollback();
            $this->error = '编辑权限规则异常';
            Log::instance()->oss(__FILE__, __LINE__, 'edit auth rule exception, msg => ' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 定义路由
     *
     * @param array $option 请求参数
     * @return boolean
     */
    public function setRoute(array $option)
    {
        $check = $this->validate()->data($option)->scope('route')->check();
        if ($check !== true) {
            $this->error = $this->validate()->getError();
            return false;
        }
        // 判断权限规则是否存在
        $baseInfo = $this->authRuleModel->getInfo(['id' => $option['idx']]);
        if (!$baseInfo) {
            $this->error = $this->authRuleModel->getError();
            return false;
        }

        $info = [
            'methods'   => implode(',', $option['methods']),
            'callback'  => $option['callback'],
            'befor'     => isset($option['befor']) ? $option['befor'] : '',
            'after'     => isset($option['after']) ? $option['after'] : '',
        ];

        $this->startTrans();
        try {
            Log::instance()->oss(__FILE__, __LINE__, 'set rule route', 'sql');
            $save = $this->save($info, ['id' => $option['idx']]);
            if (!$save) {
                $this->rollback();
                $this->error = '定义路由信息失败';
                return false;
            }

            // 记录操作日志
            $record = AdminLogModel::instance()->record(['action' => '定义路由规则', 'content' => json_encode($info, JSON_UNESCAPED_UNICODE)]);
            if (!$record) {
                $this->rollback();
                $this->error = '记录操作日志失败';
                return false;
            }

            $this->commit();
            return true;
        } catch (DbException $e) {
            $this->rollback();
            $this->error = '定义路由规则异常';
            Log::instance()->oss(__FILE__, __LINE__, 'set rule route exception, msg => ' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 自动完成create_time字段
     * 
     * @param mixed $val 默认值
     * @param array  $row 列值
     * @return string
     */
    protected function setCreateTimeAttr($val)
    {
        return time();
    }

    /**
     * 自动完成update_time字段
     * 
     * @param mixed $val 默认值
     * @param array  $row 列值
     * @return string
     */
    protected function setUpdateTimeAttr($val)
    {
        return time();
    }
}
